
use cgmath::{BaseFloat, Point3, Vector3, Vector4, Matrix4, InnerSpace};

pub struct Camera<S = f32>{
    //相机位置
    location: Point3<S>,

    //相机焦点
    center: Point3<S>,

    //相机的up轴
    world_up: Vector3<S>
}

///这里相机只作为存储相机位置，注视点，up向量的一个结构
/// 相机的运动在外部来定义
impl <S: BaseFloat + Copy> Camera<S>{
    ///指定相机位置和注视点
    pub fn new(location: Point3<S>, center: Point3<S>) -> Camera<S> {
        Camera {
            location,
            center,
            world_up:      Vector3::unit_y()
        }
    }

    /// 生成相机取景变换矩阵
    pub fn view(&self) -> Matrix4<S> {
        let x = self.center.x - self.location.x;
        let y = self.center.y - self.location.y;
        let z = self.center.z - self.location.z;
        let forward = Vector3::new(x, y, z).normalize();
        let right = self.world_up.cross(forward).normalize();
        let up = right.cross(forward).normalize();
        Matrix4::look_at(self.location, self.center, up)
    }

    ///设置注视点
    pub fn look_at(&mut self, focus: Point3<S>){
        self.center = focus
    }

    ///相机移动到这个位置
    pub fn move_to(&mut self, position: Point3<S>){
        self.location = position
    }
}